"""
===============================================
* filename: load_data.py
* author:   zhangbing
* describe: 读取邻接矩阵文件

* modifier:
* time:
* content:
===============================================
"""

RELATION_NUM = 2
ENTITY_NUM = 52
# RELATION_NUM = 2
# ENTITY_NUM = 5
import numpy as np

class DATA_PROCESSER():
    def __init__(self,dir,filename):
        self.filename = dir + filename
        self.decompose_workflow_list = []
        self.matrix_array_list = []
        self.dict_obj_to_num = {}
        self.dict_num_to_obj = {}
        self.dict_action_to_num = {}
        self.dict_num_to_action = {}
        self.dict_head_list = {}

        value = 0
        for h in range(0,ENTITY_NUM + 1):#attetion 0 stand for blank
            head_list = []
            for r in range(0,RELATION_NUM):
                for t in range(0, ENTITY_NUM + 1):
                    obj = [h,r,t]
                    self.dict_obj_to_num[str(obj)] = value
                    self.dict_num_to_obj[value] = obj
                    head_list.append(value)
                    value += 1
                self.dict_head_list[h] = head_list

        value = 0
        for h in range(0, ENTITY_NUM + 1):  # attetion 0 stand for blank
            for r in range(0, RELATION_NUM):
                for t in range(0, ENTITY_NUM + 1):
                    action = [h,r, t]
                    self.dict_action_to_num[str(action)] = value
                    self.dict_num_to_action[value] = action

                    value += 1

        # for a in self.dict_head_list[1]:
        #     print(self.num_to_obj(a))
        # pass


    def obj_to_num(self,obj):
        return self.dict_obj_to_num[str(obj)]

    def num_to_obj(self,num):
        return self.dict_num_to_obj[num]

    def action_to_num(self,action):
        return self.dict_action_to_num[str(action)]

    def num_to_action(self,num):
        return self.dict_num_to_action[num]

    def get_action_range(self,state):

        obj_num_list = list(set(state.tolist()))
        action_range = []

        entity_list = []
        for obj_num in obj_num_list:
            entity_list.append(self.num_to_obj(obj_num)[2])
            entity_list.append(self.num_to_obj(obj_num)[0])

        entity_list = list(set(entity_list))
        if 0 in entity_list:
            entity_list.remove(0)
        for id in entity_list:
            action_range.extend(self.dict_head_list[id])

        return action_range

    #从文件中读出矩阵,返回一个矩阵列表
    def read_matrix_from_file(self):

        matrix_array_list = []
        with open(self.filename, encoding='utf-8') as file_object:
            is_first_line = True
            while True:
                line = file_object.readline()
                if line == '':
                    return matrix_array_list
                if line == "#\n" or is_first_line: #第一个图不能跳
                    is_first_line = False
                    moudle_name = file_object.readline()
                    if moudle_name == '':
                        return matrix_array_list
                    matrix_data = []
                    str_data = file_object.readline().replace('-','0').split()
                    int_data = list(map(int, str_data))#转换为int
                    matrix_data.append(int_data)

                    data_length = len(int_data)
                    for i in range(data_length - 1):
                        str_data = file_object.readline().replace('-', '0').split()
                        int_data = list(map(int, str_data))
                        matrix_data.append(int_data)
                    matrix_array_list.append(matrix_data)
                else:
                    continue
    # 分解流程图
    def get_layers_of_matrix(self,matrix:list):
        length = len(matrix)
        node_type = []
        obj_list = []
        for i in range(0,length):
            node_type.append(matrix[i][i])
        #获取所有连接关系

        for i in range(0,length):
            relation = 0 #sequence relation
            is_one = 0
            if matrix[i][i] == 1:
                is_one = 1
            if matrix[i].count(1) - is_one >= 2:
                relation = 1#fork order
            for j in range(0,length):
                if j == i:
                    continue
                if matrix[i][j] == 1:
                    obj_list.append(self.obj_to_num([node_type[i],relation,node_type[j]]))

        return obj_list

    def decompose_all(self):
        for i in range(0,len(self.matrix_array_list)):
            self.decompose_workflow_list.append(self.get_layers_of_matrix(self.matrix_array_list[i]))
            print(i)

    def run(self):
        self.matrix_array_list = self.read_matrix_from_file()
        self.decompose_all()

import random

def split_list(full_list,ratio=0.8,set_seed = False,seed_num = 0):
    n_total = len(full_list)
    offset = int(n_total * ratio)
    if n_total==0 or offset<1:
        return [],full_list

    if set_seed:
        random.seed(seed_num)

    random.shuffle(full_list)
    sublist_1 = full_list[:offset]
    sublist_2 = full_list[offset:]
    return sublist_1,sublist_2

# data_processer = DATA_PROCESSER(dir="./data/",filename="workflow.txt")
data_processer = DATA_PROCESSER(dir="./data/SSD/synthetic_workflow/",filename="200.txt")
data_processer.run()
dataset = data_processer.decompose_workflow_list
dataset_train,dataset_test = split_list(full_list=dataset,ratio=0.8,set_seed=True,seed_num=11)

# dataset = []
# dataset.append([1,2,3,4,5])
# dataset.append([1,2,3,4,5,6,7,8])
pass